/* Copyright (c) 2009 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package openbang.account.service.impl;

import java.io.IOException;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.JDOObjectNotFoundException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import openbang.account.service.entity.MediaObject;
import openbang.account.service.util.PMF;
import openbang.account.service.util.SessionHelper;
import openbang.account.service.vo.BusinessEnum;

import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.blobstore.BlobstoreService;
import com.google.appengine.api.blobstore.BlobstoreServiceFactory;
import com.google.appengine.api.images.Image;
import com.google.appengine.api.images.ImagesService;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.Transform;

/**
 * 显示照片
 * 
 * 场景：
 * 1、某个页面要显示图片内容,如：用户信息页面有一栏显示图片
 * 2、图片列表里，要根据图片key，单击后显示图片参数编辑页面（如：旋转、缩放等）
 * 
 * 输入：
 * 1、必须的参数：BlobKey blobKey = new BlobKey(req.getParameter("blobKey"));
 *             或 mediaObjectId   mediaObject实体的主键
 * 2、可选的参数：rotate 翻转 （1个参数）、resize 缩放（两个参数）、crop（四个参数）
 *    2010-02-18 实现三个：nowSize , cropXY , cropSize
 * 3、输出方式   outputType = stream , view , modify  缺省为 stream
 * 输出：根据  输出方式   outputType 选择：
 * 1、以流的方式输出图片内容
 * 2、以html方式，显示图片各种明细信息（如：文件名）和显示控制参数（旋转、缩放等）.
 *  * 
 * @author aibo zeng
 *
 */

@SuppressWarnings("serial")
public class DisplayPhotoServlet extends HttpServlet {
  private static final Logger log = Logger.getLogger(DisplayPhotoServlet.class.getName());
  private BlobstoreService blobstoreService =
    BlobstoreServiceFactory.getBlobstoreService();

  public void doGet(HttpServletRequest req, HttpServletResponse resp)
  throws IOException {
	  doPost(req,resp);
  }
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException {

	PersistenceManager pm = PMF.get().getPersistenceManager();
	MediaObject mediaObject = null;
	String mediaObjectIdStr = req.getParameter("mediaObjectId");
	String blobKeyStr = req.getParameter("blobKey");
	if(mediaObjectIdStr!=null && !"".equals(mediaObjectIdStr)){
		//以 mediaObjectIdStr 为准
		try{
		  mediaObject = pm.getObjectById(MediaObject.class,Long.parseLong(mediaObjectIdStr));
		  blobKeyStr = mediaObject.getBlobKey();
		}catch(NumberFormatException ne){			
		}catch(JDOObjectNotFoundException jdoe){			
		}
	}
	else{
	    Query query = pm.newQuery(MediaObject.class, "blobKey == blobKeyParam");
	    query.declareParameters("String blobKeyParam");
	    List<MediaObject> results = (List<MediaObject>) query.execute(blobKeyStr);
	    if (results.isEmpty()) {
		  SessionHelper.forwardToErrorPage(BusinessEnum.DISPLAY_PHOTO.getDesc(),"没有找到图片","请重新登录", req, resp);       
	      return;
	    }
	    mediaObject = results.get(0);
	}
	
    //图片处理的参数
    String rotation = req.getParameter("rotate");
    String businessType = req.getParameter("businessType");
    String outputType = req.getParameter("outputType");
    String nowSize = req.getParameter("nowSize");
    String cropXY = req.getParameter("cropXY");
    String cropSize = req.getParameter("cropSize");
    String orgiSize = req.getParameter("orgiSize");//原始像素
    
    if(outputType==null || "null".equals(outputType)){
    	outputType="stream";
    }
    StringBuffer logSb = new StringBuffer();
    logSb.append("blobKey="+blobKeyStr);
    logSb.append(",rotate="+rotation);//degrees - 要旋转的度数。必须为 90 的倍数。 
    logSb.append(",outputType="+outputType);
    logSb.append(",nowSize="+nowSize);
    logSb.append(",cropXY="+cropXY);
    logSb.append(",cropSize="+cropSize);
    
    log.warning(logSb.toString());
    
    int resizeW = 0;
    int resizeH = 0;
    int cropW = 0;
    int cropH = 0;
    int cropX = 0;
    int cropY = 0;
    int orgiW = 0;
    int orgiH = 0;
    
    //裁剪图片时的图片宽高。当没有缩放时，为原始图片的宽高，当有缩放时，为缩放后的宽高。
    //因为从图片服务器取出image时，使用 getWidth()会得到 ：java.lang.UnsupportedOperationException: No image data is available.
    //所以,另设变量来获取
    int newImageWidth = 0;
    int newImageHeight = 0;
    
    //根据传入参数来决定是否需要处理图片
    boolean needProcess = false;
    if(nowSize!=null && nowSize.length()>0){
    	needProcess = true;
    	String[] newSizeArr = nowSize.split("\\*");
    	resizeW = Integer.parseInt(newSizeArr[0]);
    	resizeH = Integer.parseInt(newSizeArr[1]);
    }
    if(cropXY!=null && cropXY.length()>0){
    	needProcess = true;
    	String[] cropArr = cropXY.split(",");
    	cropX = Integer.parseInt(cropArr[0]);
    	cropY = Integer.parseInt(cropArr[1]);    	
    }
    if(cropSize!=null && cropSize.length()>0){
    	needProcess = true;
    	String[] cropSizeArr = cropSize.split("\\*");
    	cropW = Integer.parseInt(cropSizeArr[0]);
    	cropH = Integer.parseInt(cropSizeArr[1]);    	
    }
    
    //2010-02-19 原始图片的像素大小，只能从界面传入
    if(orgiSize!=null && orgiSize.length()>0){
    	//needProcess = true;
    	String[] orgiSizeArr = orgiSize.split("\\*");
    	orgiW = Integer.parseInt(orgiSizeArr[0]);
    	orgiH = Integer.parseInt(orgiSizeArr[1]);  
    	newImageWidth = orgiW;
    	newImageHeight = orgiH;
    }
    
    
    Image respImage = null;
    BlobKey blobKey = null;
    if(needProcess){
    	//从 GAE 取出 图片文件
    	blobKey = new BlobKey(blobKeyStr);
        ImagesService imagesService = ImagesServiceFactory.getImagesService();
        Image image = ImagesServiceFactory.makeImageFromBlob(blobKey);
        if(image==null){
  		    SessionHelper.forwardToErrorPage(BusinessEnum.DISPLAY_PHOTO.getDesc(),"从图片服务器没有找到图片","请重新登录", req, resp);
  		    return;
        }
        //1.先处理翻转  -- 暂不实现
        //if (rotation == null || "".equals(rotation) || "null".equals(rotation)) {
        //	rotation="0";
        //}
        //int degrees = Integer.parseInt(rotation);
        //if (degrees!=0){        	
        //    Transform rotate = ImagesServiceFactory.makeRotate(degrees);
        //    Image newImage = imagesService.applyTransform(rotate, image);
    	//2.处理缩放    makeResize(int width, int height)
        if(resizeW!=0 && resizeH!=0 && resizeW!=newImageWidth && resizeH!=newImageHeight){
           Transform transform = ImagesServiceFactory.makeResize(resizeW, resizeH);
           respImage = imagesService.applyTransform(transform,image);
           image = respImage;
           newImageWidth = resizeW;
           newImageHeight = resizeH;
           
        }
        //3.处理剪裁
        /*创建裁剪图像以符合指定边界框的转换。参数以总图像大小的百分比来定义用于裁剪图像的边界框的左上角和右下角。每个参数应在 0.0 至 1.0 的范围内（包括 0.0 和 1.0）。

        参数：
            leftX - 边界框的左上角的 X 坐标
            topY - 边界框的左上角的 Y 坐标
            rightX - 边界框的右下角的 X 坐标
            bottomY - 边界框的右下角的 Y 坐标 
            */
        if(cropW>0 && cropH>0){
        	log.warning("image.getWidth()="+newImageWidth);//java.lang.UnsupportedOperationException: No image data is available.
        	log.warning("image.getHeight()="+newImageHeight);
            Transform transform = ImagesServiceFactory.makeCrop(cropX*1.0/newImageWidth, cropY*1.0/newImageHeight, (cropX+cropW)*1.0/newImageWidth, (cropY+cropH)*1.0/newImageHeight);
            respImage = imagesService.applyTransform(transform,image);        	
        }
    }
    
    if("stream".equals(outputType)){
    	//输出 "流"   再区分两种情况
    	if(needProcess && respImage!=null){
            byte[] imgbyte = respImage.getImageData();
            resp.setContentType(mediaObject.getContentType());
            resp.getOutputStream().write(imgbyte);
        }
    	else{
    		if(blobKey==null){
    			blobKey = new BlobKey(blobKeyStr);
    		}
    		resp.setContentType(mediaObject.getContentType());
            blobstoreService.serve(blobKey, resp);
    	}
    	//注：如果处理过,必须以流的方式显示，否则白处理了
    }
    else{
    	//输出"html"
    	  req.setAttribute("mediaObject",mediaObject);
    	  req.setAttribute("businessType",businessType);
    	  try {
  			req.getRequestDispatcher("/WEB-INF/jsp/displayPhotoParam.jsp").forward(req, resp);
	  	  } catch (ServletException e) {
	  	  } catch (IOException e) {
	  	  }    	  
    }
    log.warning("DisplayPhotoServlet over.");
  }
}
